﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace CommonTools
{
    public class CommonTool
    {
        #region 网络地址相关
        /// <summary>
        /// 将字符串网络地址格式转换成IPEndPoint
        /// </summary>
        /// <param name="ipendpoint"></param>
        /// <returns></returns>
        public static IPEndPoint CvStr2IPEndPoint(string ipendpoint)
        {
            string[] str = ipendpoint.Split(':');
            if (str.Length == 2)
            {
                return new IPEndPoint(IPAddress.Parse(str[0]), int.Parse(str[1]));
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        ///获取IPv4的地址 
        /// </summary>
        /// <returns></returns>
        public static string GetIpAddress()
        {
            string hostName = Dns.GetHostName();   //获取本机名
            IPHostEntry localhost = Dns.GetHostByName(hostName);    //方法已过期，可以获取IPv4的地址
                                                                    //IPHostEntry localhost = Dns.GetHostEntry(hostName);   //获取IPv6地址
            IPAddress localaddr = localhost.AddressList[0];

            return localaddr.ToString();
        }
        /// <summary>
        /// 获取字符串网络地址IPAddress
        /// </summary>
        /// <param name="ipendpoint"></param>
        /// <returns></returns>
        public static IPAddress CvStr2IPAddress(string ipendpoint)
        {
            string[] str = ipendpoint.Split(':');
            if (str.Length == 2)
            {
                return IPAddress.Parse(str[0]);
            }
            else
            {
                return null;
            }
        }
        /// <summary>
        /// 获取字符串网络地址端口
        /// </summary>
        /// <param name="ipendpoint"></param>
        /// <returns></returns>
        public static int CvStr2Port(string ipendpoint)
        {
            string[] str = ipendpoint.Split(':');
            if (str.Length == 2)
            {
                return int.Parse(str[1]);
            }
            else
            {
                return 0;
            }
        }
        /// <summary>
        /// 判断提供的IPEndPoint地址与本地网络地址是否相同
        /// </summary>
        /// <param name="ipAddress"></param>
        /// <returns></returns>
        public static bool CompareTolocalIP(string ipendpoint)
        {
            IPAddress temp = CommonTool.CvStr2IPAddress(ipendpoint);         //从配置文件中获取SceneIP
            IPAddress[] ips = Dns.GetHostAddresses(Dns.GetHostName());
            foreach (IPAddress ip in ips)                                           //判断是否符合配置文件中设置IP
            {
                if (Regex.IsMatch(temp.ToString(), ip.ToString()))
                {
                    return true;
                }
            }
            return false;
        }
        #endregion
        #region   序列化与反序列化
        /// <summary>
        /// 类序列化为byte[]
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static byte[] ArraySerialize(object obj)
        {
            MemoryStream stream = new MemoryStream();
            BinaryFormatter bf = new BinaryFormatter();
            bf.Serialize(stream, obj);
            byte[] newArray = new byte[stream.Length];
            stream.Position = 0;
            stream.Read(newArray, 0, (int)stream.Length);
            stream.Close();
            return newArray;
        }
        /// <summary>
        /// byte[]反序列化为类
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public static object ArrayDeserialize(byte[] array)
        {
            MemoryStream stream = new MemoryStream(array);
            BinaryFormatter bf = new BinaryFormatter();
            Object obj = bf.Deserialize(stream);
            stream.Close();
            return obj;
        }
        #endregion
        #region 比较器
        /// <summary>
        /// 判断两个BIT是否相等
        /// </summary>
        /// <param name="A"></param>
        /// <param name="B"></param>
        /// <returns></returns>
        public static bool SameBitArray(BitArray A, BitArray B)
        {
            if (A == null || B == null) return false;
            if (A.Length != B.Length) return false;
            for (int i = 0; i < A.Length; i++)
                if (A[i] != B[i]) return false;
            return true;
        }
        #endregion

        /// <summary>
        /// 如果有相同程序运行则不启动新程序
        /// </summary>
        /// <param name="processName"></param>
        /// <returns></returns>
        public static bool CheckSameProcedure(string processName)
        {
            Process[] preceses = Process.GetProcessesByName(processName);
            if (preceses.Length >1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// Ping IP地址
        /// </summary>
        /// <param name="processName"></param>
        /// <returns></returns>
        public static bool PingIp(string ipAddress)
        {
            try
            {
                Ping ping = new Ping();
                PingReply pingReply = ping.Send(ipAddress);
                if (pingReply.Status == IPStatus.Success)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch 
            {

                return false;
            }
            
        }
        /// <summary>
        /// 检测本机是否联网
        /// </summary>
        /// <returns></returns>
        public static bool IsConnectedInternet()
        {
            int i = 0;
            if (InternetGetConnectedState(out i, 0))
            {
                //已联网
                return true;
            }
            else
            {
                //未联网
                return false;
            }
        }
        [DllImport("wininet")]
        private extern static bool InternetGetConnectedState(out int connectionDescription, int reservedValue);

        #region 经纬度转换方法

        /// <summary>
        /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion)
        /// </summary>
        /// <param name="digitalLati_Longi">数字经纬度</param>
        /// <return>度分秒经纬度</return>
        static public string ConvertDigitalToDegrees(string digitalLati_Longi)
        {
            double digitalDegree = Convert.ToDouble(digitalLati_Longi);
            return ConvertDigitalToDegrees2(digitalDegree);
        }

        /// <summary>
        /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion)
        /// </summary>
        /// <param name="digitalDegree">数字经纬度</param>
        /// <return>度分秒经纬度</return>
        static public string ConvertDigitalToDegrees(double digitalDegree)
        {
            const double num = 60;
            int degree = (int)digitalDegree;
            double tmp = (digitalDegree - degree) * num;
            int minute = (int)tmp;
            double second = (tmp - minute) * num;
            string degrees = "" + degree + "°" + minute + "′" + second + "″";
            return degrees;
        }
        /// <summary>
        /// 数字经纬度和度分秒经纬度转换 (Digital degree of latitude and longitude and vehicle to latitude and longitude conversion)
        /// </summary>
        /// <param name="digitalDegree">数字经纬度</param>
        /// <return>度分秒经纬度</return>
        static public string ConvertDigitalToDegrees2(double digitalDegree)
        {
            const double num = 60;
            int degree = (int)digitalDegree;
            double tmp = (digitalDegree - degree) * num;
            string degrees = "" + degree + "°" + tmp.ToString("N2") + "′";
            return degrees;
        }
        /// <summary>
        /// 度分秒经纬度(必须含有'°')和数字经纬度转换
        /// </summary>
        /// <param name="digitalDegree">度分秒经纬度</param>
        /// <return>数字经纬度</return>
        static public double ConvertDegreesToDigital(string degrees)
        {
            const double num = 60;
            double digitalDegree = 0.0;
            int d = degrees.IndexOf('°');           //度的符号对应的 Unicode 代码为：00B0[1]（六十进制），显示为°。
            if (d < 0)
            {
                return digitalDegree;
            }
            string degree = degrees.Substring(0, d);
            digitalDegree += Convert.ToDouble(degree);

            int m = degrees.IndexOf('′');           //分的符号对应的 Unicode 代码为：2032[1]（六十进制），显示为′。
            if (m < 0)
            {
                return digitalDegree;
            }
            string minute = degrees.Substring(d + 1, m - d - 1);
            digitalDegree += ((Convert.ToDouble(minute)) / num);

            int s = degrees.IndexOf('″');           //秒的符号对应的 Unicode 代码为：2033[1]（六十进制），显示为″。
            if (s < 0)
            {
                return digitalDegree;
            }
            string second = degrees.Substring(m + 1, s - m - 1);
            digitalDegree += (Convert.ToDouble(second) / (num * num));

            return digitalDegree;
        }


        /// <summary>
        /// 度分秒经纬度(必须含有'/')和数字经纬度转换
        /// </summary>
        /// <param name="digitalDegree">度分秒经纬度</param>
        /// <param name="cflag">分隔符</param>
        /// <return>数字经纬度</return>
        static public double ConvertDegreesToDigital_default(string degrees)
        {
            char ch = '/';
            return ConvertDegreesToDigital(degrees, ch);
        }

        /// <summary>
        /// 度分秒经纬度和数字经纬度转换
        /// </summary>
        /// <param name="digitalDegree">度分秒经纬度</param>
        /// <param name="cflag">分隔符</param>
        /// <return>数字经纬度</return>
        static public double ConvertDegreesToDigital(string degrees, char cflag)
        {
            const double num = 60;
            double digitalDegree = 0.0;
            int d = degrees.IndexOf(cflag);
            if (d < 0)
            {
                return digitalDegree;
            }
            string degree = degrees.Substring(0, d);
            digitalDegree += Convert.ToDouble(degree);

            int m = degrees.IndexOf(cflag, d + 1);
            if (m < 0)
            {
                return digitalDegree;
            }
            string minute = degrees.Substring(d + 1, m - d - 1);
            digitalDegree += ((Convert.ToDouble(minute)) / num);

            int s = degrees.Length;
            if (s < 0)
            {
                return digitalDegree;
            }
            string second = degrees.Substring(m + 1, s - m - 1);
            digitalDegree += (Convert.ToDouble(second) / (num * num));

            return digitalDegree;
        }

        #endregion
        /// <summary>
        /// 字节数组转16进制字符串：空格分隔
        /// </summary>
        /// <param name="byteDatas"></param>
        /// <returns></returns>
        public static string ToHexStrFromByte(byte[] byteDatas)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < byteDatas.Length; i++)
            {
                builder.Append(string.Format("{0:X2} ", byteDatas[i]));
            }
            return builder.ToString().Trim();
        }
        //发送时将结构体数据转换成字节数组
        public static byte[] StructToBytes(object obj)
        {
            //得到结构体的大小
            int size = Marshal.SizeOf(obj);
            //创建byte数组
            byte[] bytes = new byte[size];
            //分配结构体大小的内存空间
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(obj, structPtr, false);
            //从内存空间拷到byte数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            //返回byte数组
            return bytes;
        }
    }
}
